#include "views/filterview.h"
#include "ui_filterview.h"

FilterView::FilterView(QWidget *parent) :
	QWidget(parent),
    m_ui(new Ui::FilterView)
{
    m_ui->setupUi(this);
	connect(m_ui->correlationMode,SIGNAL(currentIndexChanged(int)),this,SLOT(oncorrModeIndexChanged(int)));
	connect(m_ui->distanceMode,SIGNAL(currentIndexChanged(int)),this,SLOT(ondistModeIndexChanged(int)));
	connect(m_ui->filterDeviationMode,SIGNAL(currentIndexChanged(int)),this,SLOT(ondevModeIndexChanged(int)));
	
	connect(m_ui->correlationAboveSlider,SIGNAL(sliderMoved(double)),this,SLOT(oncorrAboveValueChanged(double)));
	connect(m_ui->correlationBelowSlider,SIGNAL(sliderMoved(double)),this,SLOT(oncorrBelowValueChanged(double)));
	connect(m_ui->distanceAboveSlider,SIGNAL(sliderMoved(double)),this,SLOT(ondistAboveValueChanged(double)));
	connect(m_ui->distanceBelowSlider,SIGNAL(sliderMoved(double)),this,SLOT(ondistBelowValueChanged(double)));

	connect(m_ui->filterDeviationSlider,SIGNAL(sliderMoved(double)),this,SLOT(ondeviationValueChanged(double)));

	corrFilter = new CorrelationFilter();
	distFilter = new DistanceFilter();
	expFilter = new DeviationFromExpectedFilter();

	showCorrBetweenRow(false);
	showDistBetweenRow(false);

	network = NULL;
}

FilterView::~FilterView()
{
    delete m_ui;
}

void FilterView::ondeviationValueChanged(double val)
{
	expFilter->setDeviationValue(val/100.0);
}

void FilterView::oncorrModeIndexChanged(int idx)
{
	switch(idx)
	{
	case 0: //Minimum
		{
			corrFilter->setFilterToAcceptAbove(m_ui->correlationAboveSlider->value());
			showCorrBetweenRow(false);
		};break;
	case 1: //Maximum
		{
			corrFilter->setFilterToAcceptBelow(m_ui->correlationAboveSlider->value());
			showCorrBetweenRow(false);
		};break;
	case 2: //Between
		{
			corrFilter->setFilterToAcceptBetween(m_ui->correlationAboveSlider->value(),m_ui->correlationBelowSlider->value());
			showCorrBetweenRow(true);
		};break;
	}
}

void FilterView::ondevModeIndexChanged(int idx)
{
	switch(idx)
	{
	case 0: //Minimum
		{
			expFilter->setFilterMode(DeviationFromExpectedFilter::BetweenIn);
		};break;
	case 1: //Maximum
		{
			expFilter->setFilterMode(DeviationFromExpectedFilter::BetweenOut);
		};break;
	}
}

void FilterView::showCorrBetweenRow(bool show)
{
	m_ui->label->setVisible(show);
	m_ui->correlationBelowSlider->setVisible(show);
	m_ui->correlationBelowLabel->setVisible(show);
}

void FilterView::showDistBetweenRow(bool show)
{
	m_ui->label_2->setVisible(show);
	m_ui->distanceBelowSlider->setVisible(show);
	m_ui->distanceBelowLabel->setVisible(show);
}

void FilterView::setMinimumCorrelation(double min)
{
	m_ui->correlationAboveSlider->setRange(min,m_ui->correlationAboveSlider->maxValue());
	m_ui->correlationBelowSlider->setRange(min,m_ui->correlationBelowSlider->maxValue());
}

void FilterView::setMaximumCorrelation(double max)
{
	m_ui->correlationAboveSlider->setRange(m_ui->correlationAboveSlider->minValue(),max);
	m_ui->correlationBelowSlider->setRange(m_ui->correlationBelowSlider->minValue(),max);
}


void FilterView::setMinimumDistance(double min)
{
	m_ui->distanceAboveSlider->setRange(min,m_ui->distanceAboveSlider->maxValue());
	m_ui->distanceBelowSlider->setRange(min,m_ui->distanceBelowSlider->maxValue());
}

void FilterView::setMaximumDistance(double max)
{
	m_ui->distanceAboveSlider->setRange(m_ui->distanceAboveSlider->minValue(),max);
	m_ui->distanceBelowSlider->setRange(m_ui->distanceBelowSlider->minValue(),max);
}

void FilterView::ondistModeIndexChanged(int idx)
{
	switch(idx)
	{
	case 0: //Minimum
		{
			distFilter->setFilterToAcceptAbove(m_ui->distanceAboveSlider->value());
			showDistBetweenRow(false);
		};break;
	case 1: //Maximum
		{
			distFilter->setFilterToAcceptBelow(m_ui->distanceAboveSlider->value());
			showDistBetweenRow(false);
		};break;
	case 2: //Between
		{
			distFilter->setFilterToAcceptBetween(m_ui->distanceAboveSlider->value(),m_ui->distanceBelowSlider->value());
			showDistBetweenRow(true);
		};break;
	}
}

void FilterView::oncorrAboveValueChanged(double value)
{
	switch(m_ui->correlationMode->currentIndex())
	{
	case 0: //Minimum
		{
			corrFilter->setFilterToAcceptAbove(value);
		};break;
	case 1: //Maximum
		{
			corrFilter->setFilterToAcceptBelow(value);
		};break;
	case 2: //Between
		{
			corrFilter->setFilterToAcceptBetween(value,m_ui->correlationBelowSlider->value());
		};break;
	}
}

void FilterView::oncorrBelowValueChanged(double value)
{
	corrFilter->setFilterToAcceptBetween(m_ui->correlationAboveSlider->value(),value);
}

void FilterView::ondistAboveValueChanged(double value)
{
	switch(m_ui->distanceMode->currentIndex())
	{
	case 0: //Minimum
		{
			distFilter->setFilterToAcceptAbove(value);
		};break;
	case 1: //Maximum
		{
			distFilter->setFilterToAcceptBelow(value);
		};break;
	case 2: //Between
		{
			distFilter->setFilterToAcceptBetween(value,m_ui->distanceBelowSlider->value());

		};break;
	}
}

void FilterView::ondistBelowValueChanged(double value)
{
	distFilter->setFilterToAcceptBetween(m_ui->distanceAboveSlider->value(),value);
}

void FilterView::setNetwork(FunctionalNetwork *net)
{
	network = net;

	expFilter->setNetwork(network);

	network->addFilter(expFilter);
	network->addFilter(distFilter);
	network->addFilter(corrFilter);

	m_ui->filterDeviationSlider->setRange(0,100);
	m_ui->filterDeviationSlider->setValue(100);

	on_matrixChanged();
	m_ui->correlationAboveSlider->setValue(network->getCurrentIndividualMatrix()->minValue());
	m_ui->correlationBelowSlider->setValue(network->getCurrentIndividualMatrix()->maxValue());
	m_ui->distanceAboveSlider->setValue(network->minimumDistance());
	m_ui->distanceBelowSlider->setValue(network->maximumDistance());
	oncorrAboveValueChanged(network->getCurrentIndividualMatrix()->minValue());
	ondeviationValueChanged(100);

	connect(corrFilter,SIGNAL(filterChanged(LinkFilter*)),network,SLOT(on_filterChanged(LinkFilter*)));
	connect(distFilter,SIGNAL(filterChanged(LinkFilter*)),network,SLOT(on_filterChanged(LinkFilter*)));
	connect(expFilter,SIGNAL(filterChanged(LinkFilter*)),network,SLOT(on_filterChanged(LinkFilter*)));

}

void FilterView::on_matrixChanged()
{
	if(!network)
		return;
		
	setMinimumCorrelation(network->getCurrentIndividualMatrix()->minValue());
	setMaximumCorrelation(network->getCurrentIndividualMatrix()->maxValue());

	setMinimumDistance(network->minimumDistance());
	setMaximumDistance(network->maximumDistance());
}